package cn.kinoko.service;

import org.redisson.api.*;
import org.redisson.client.protocol.ScoredEntry;

import java.lang.reflect.InvocationTargetException;
import java.time.Duration;
import java.util.*;

/**
 * Redis服务API
 *
 * @author kinoko
 */
public interface RedisService {

    /**
     * 获取所有匹配的key
     * command: keys pattern
     *
     * @param pattern 匹配的key
     * @return 匹配的key
     */
    Iterable<String> getKeys(String pattern);

    /**
     * 获取缓存类型
     * command: type key
     *
     * @param key key
     * @return 类型
     */
    Optional<?> matchTypeAndGet(String key);

    /**
     * 匹配类型并设置缓存
     *
     * @param key key
     * @param value  value
     * @param expire 过期时间
     */
    <V> void matchTypeAndSet(String key, V value, Duration expire) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException;

    /**
     * 设置缓存
     * command: set key value
     *
     * @param key   key
     * @param value value
     */
    <V> void set(String key, V value);

    /**
     * 设置缓存
     * command: set key value [ex seconds] [px milliseconds]
     *
     * @param key      key
     * @param value    value
     * @param expire   过期时间
     */
    void set(String key, Object value, Duration expire);

    /**
     * 批量设置多个缓存
     * command: mset key value [key value …]
     *
     * @param temps temps
     */
    <V> void multiSet(Map<String, V> temps);

    /**
     * 获取缓存
     * command: get key
     *
     * @param key key
     * @return value
     */
    <V> V get(String key);

    /**
     * 获取所有匹配 pattern 的缓存key 对应的缓存值
     * 此方法 谨慎使用
     *
     * @param pattern pattern
     * @return 匹配的缓存值
     */
    <V> Set<V> getAll(String pattern);

    /**
     * 获取缓存过期时间
     * command: ttl key
     *
     * @param key key
     * @return 剩余时间
     */
    Long ttl(String key);

    /**
     * 删除缓存
     * command: del key
     *
     * @param key key
     * @return 是否删除成功
     */
    boolean del(String key);

    /**
     * 删除所有匹配 pattern 的缓存key
     * command: del key
     *
     * @param pattern pattern
     */
    void delAll(String pattern);

    /**
     * 获取Map
     * command: hset key
     *
     * @param key        key
     * @param expireTime 过期时间
     * @return Map
     */
    <K, V> RMap<K, V> getMap(String key, Duration expireTime);

    /**
     * 获取Map
     * command: hset key
     *
     * @param key key
     * @return Map
     */
    <K, V> RMap<K, V> getMap(String key);

    /**
     * Map中是否存在field
     * command: hexists key field
     *
     * @param key   key
     * @param field field
     * @return 是否存在
     */
    <K> boolean hasMapKey(String key, K field);

    /**
     * 获取Map中的所有field
     * command: hkeys key
     *
     * @param key key
     * @return field集合
     */
    Set<Object> getMapKeyList(String key);

    /**
     * 获取Map中的所有value
     * command: hvals key
     *
     * @param key key
     * @return value集合
     */
    List<Object> getMapValueList(String key);

    /**
     * 设置Map中的field
     * command: hset key field value
     *
     * @param key   key
     * @param field field
     * @param value value
     */
    <K, V> void putMapEntry(String key, K field, V value);

    /**
     * 设置Map中的field
     * command: hset key field value [ex seconds] [px milliseconds]
     *
     * @param key        key
     * @param field      field
     * @param value      value
     * @param expireTime 过期时间
     */
    <K, V> void putMapEntry(String key, K field, V value, Duration expireTime);

    /**
     * 获取Map中的field
     * command: hget key field
     *
     * @param key   key
     * @param field field
     * @return value
     */
    <K, V> V getMapValue(String key, K field);

    /**
     * 删除Map中的field
     * command: hdel key field
     *
     * @param key   key
     * @param field field
     */
    <K> void delValue(String key, K field);

    /**
     * 获取List
     * command: lset key
     *
     * @param key        key
     * @param expireTime 过期时间
     * @return List
     */
    <V> RList<V> getList(String key, Duration expireTime);

    /**
     * 获取List
     * command: lset key
     *
     * @param key key
     * @return List
     */
    <V> RList<V> getList(String key);

    /**
     * 删除List元素
     * command: lrem key count value
     *
     * @param key     key
     * @param element 元素
     * @return 是否删除成功
     */
    <V> boolean delListElement(String key, V element);

    /**
     * 获取Set
     * command: sset key
     *
     * @param key key
     * @return Set
     */
    <V> RSet<V> getSet(String key, Duration expireTime);

    /**
     * 获取Set
     * command: sset key
     *
     * @param key key
     * @return Set
     */
    <V> RSet<V> getSet(String key);

    /**
     * 是否有Set元素
     * command: sismember key member
     *
     * @param key     key
     * @param element 元素
     * @return 是否存在
     */
    <V> boolean hasSetElement(String key, V element);

    /**
     * 删除Set 元素
     * command: srem key member
     *
     * @param key     key
     * @param element 元素
     * @return 是否删除成功
     */
    <V> boolean delSetElement(String key, V element);

    /**
     * 获取Zset
     * Command: zset key
     *
     * @param key key
     * @return 有序集合
     */
    <V> RScoredSortedSet<V> getScoredSortedSet(String key, Duration expireTime);

    /**
     * 获取Zset
     * command: zset key
     *
     * @param key key
     * @return 有序集合
     */
    <V> RScoredSortedSet<V> getScoredSortedSet(String key);

    /**
     * 分数排序集合添加元素
     * 默认从低分到高分排序
     * command: zadd key score member
     *
     * @param key     key
     * @param element 元素
     */
    <V> void addScoredSortedSetElement(String key, V element);

    /**
     * 分数排序集合添加元素
     * 默认从低分到高分排序
     * 指定分数
     * command: zadd key score member
     *
     * @param key     key
     * @param element 元素
     * @param score   分数
     */
    <V> void addScoredSortedSetElement(String key, V element, double score);

    /**
     * 获取分数排序集合
     * 以相反的顺序按排名范围返回值
     * command: zrevrange key start stop
     *
     * @param key        key
     * @param startIndex 开始下标
     * @param endIndex   结束下标
     * @return 元素集合
     */
    <V> Collection<V> getScoredSortedSetValueRangeReversed(String key, int startIndex, int endIndex);

    /**
     * 获取分数排序集合
     * 顺序按排名范围返回值
     * command: zrange key start stop
     *
     * @param key        key
     * @param startIndex 开始下标
     * @param endIndex   结束下标
     * @return 元素集合
     */
    <V> Collection<V> getScoredSortedSetValueRange(String key, int startIndex, int endIndex);

    /**
     * 获取分数排序集合
     * 以相反的顺序按排名范围返回值
     * command: zrevrange key 0 -1
     *
     * @param key key
     * @return 元素集合
     */
    <V> Collection<V> getScoredSortedSetValueReversed(String key);

    /**
     * 获取分数排序集合
     * 顺序按排名范围返回值
     * command: zrange key 0 -1
     *
     * @param key key
     * @return 元素集合
     */
    <V> Collection<V> getScoredSortedSetValue(String key);

    /**
     * 获取分数排序集合
     * 以相反的顺序按排名范围返回条目（值及其分数）
     * command: zrevrange key start stop withscores
     *
     * @param key        key
     * @param startIndex 开始下标
     * @param endIndex   结束下标
     * @return 元素集合
     */
    <V> Collection<ScoredEntry<V>> getScoredSortedSetEntryRangeReversed(String key, int startIndex, int endIndex);

    /**
     * 获取分数排序集合
     * 顺序按排名范围返回条目（值及其分数）
     * command: zrange key start stop withscores
     *
     * @param key        key
     * @param startIndex 开始下标
     * @param endIndex   结束下标
     * @return 元素集合
     */
    <V> Collection<ScoredEntry<V>> getScoredSortedSetEntryRange(String key, int startIndex, int endIndex);

    /**
     * 获取分数排序集合
     * 以相反的顺序按排名范围返回条目（值及其分数）
     * command: zrevrange key 0 -1 withscores
     *
     * @param key key
     * @return 元素集合
     */
    <V> Collection<ScoredEntry<V>> getScoredSortedSetEntryReversed(String key);

    /**
     * 获取分数排序集合
     * 顺序按排名范围返回条目（值及其分数）
     * command: zrange key 0 -1 withscores
     *
     * @param key key
     * @return 元素集合
     */
    <V> Collection<ScoredEntry<V>> getScoredSortedSetEntry(String key);

    /**
     * 获取元素分数
     * command: zscore key member
     *
     * @param key     key
     * @param element 元素
     * @return 分数
     */
    <V> Double getElementScore(String key, V element);

    /**
     * 是否存在该元素
     * command: zscore key member
     *
     * @param key     key
     * @param element 元素
     * @return 是否存在
     */
    <V> boolean hasScoredSortedSetElement(String key, V element);

    /**
     * 删除指定元素
     * command: zrem key member
     *
     * @param key     key
     * @param element 元素
     * @return 是否删除成功
     */
    <V> boolean delScoredSortedSetElement(String key, V element);

    /**
     * 获取元素排名（从0开始计数）
     * command: zrank key member
     *
     * @param key     key
     * @param element 元素
     * @return 排名
     */
    <V> int getRankFormScoredSortedSet(String key, V element);

    /**
     * 获取元素倒排名（从0开始计数）
     * command: zrevrank key member
     *
     * @param key     key
     * @param element 元素
     * @return 排名
     */
    <V> int getReversedRankFormScoredSortedSet(String key, V element);

    /**
     * 增加元素分数
     * 当分数为负数时，减少分数
     * command: zincrby key score member
     *
     * @param key     key
     * @param element 元素
     * @param score   分数
     */
    <V> void incrementElementScore(String key, V element, int score);

    /**
     * 获取分布式锁
     *
     * @param key key
     * @return 锁
     */
    RLock getLock(String key);

    /**
     * 获取分布式限流器
     *
     * @param key key
     * @return 限流器
     */
    RRateLimiter getRateLimiter(String key);

    /**
     * 获取脚本对象
     *
     * @return 脚本对象
     */
    RScript getLuaScript();

    /**
     * 获取布隆过滤器
     *
     * @param redisKey redisKey
     * @return bloomFilter
     */
    <T> RBloomFilter<T> getBloomFilter(String redisKey);
}
